(define-module (staging modsec)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (guix packages)
  #:use-module (guix download)
  #:use-module (guix git-download)
  #:use-module (guix utils)
  #:use-module (gnu packages apr)
  #:use-module (gnu packages autotools)
  #:use-module (gnu packages web)
  #:use-module (gnu packages compression)
  #:use-module (gnu packages curl)
  #:use-module (gnu packages gettext)
  #:use-module (gnu packages tls)
  #:use-module (gnu packages libevent)
  #:use-module (gnu packages texinfo)
  #:use-module (gnu packages pcre)
  #:use-module (gnu packages perl)
  #:use-module (gnu packages pkg-config)
  #:use-module (gnu packages python)
  #:use-module (gnu packages version-control)
  #:use-module (gnu packages xml)
  #:use-module (guix build-system gnu)
  #:use-module (guix build-system trivial))

(define-public gnulib
  (let ((commit "de255f87357354e0f2422d9321fe9701b776ead5")
        (revision "1"))
    (package
      (name "gnulib")
      (version "0.0.0")
      (source (origin
                (method git-fetch)
                (uri (git-reference
                      (url "https://git.savannah.gnu.org/git/gnulib.git")
                      (commit commit)))
                (file-name (git-file-name name version))
                (sha256
                 (base32
                  "00zjjldhj8ckr47fkqmb4d0lkpn6awwi8k8pngkfn2g30ccz7hji"))))
      (build-system gnu-build-system)
      (arguments
       `(#:tests? #f
         #:phases (modify-phases %standard-phases
                    (delete 'configure)
                    (delete 'build)
                    (add-after 'install 'patch-yet-again
                      (lambda* (#:key outputs #:allow-other-keys)
                        (for-each patch-shebang (find-files (assoc-ref outputs "out")))
                        #t))
                    (replace 'install
                      (lambda* (#:key inputs outputs #:allow-other-keys)
                        (let ((source (assoc-ref inputs "source"))
                              (out (assoc-ref outputs "out")))
                          (copy-recursively source out)
                          #t))))))
      (home-page "https://www.gnu.org/software/gnulib/")
      (synopsis "")
      (description "")
      ;; TODO: omg wtf
      (license #f))))

(define-public pax-utils
  (package
    (name "pax-utils")
    (version "1.2.4")
    (source (origin
              (method url-fetch)
              (uri (string-append
                    "http://distfiles.gentoo.org/distfiles/pax-utils-"
                    version ".tar.xz"))
              (sha256
               (base32
                "01kr6l2c3bhbgdrmwgzh6jk0jjkw3pi9xrzzl9cpn0ibyf68p1aj"))))
    (build-system gnu-build-system)
    (home-page "https://wiki.gentoo.org/wiki/Hardened/PaX_Utilities")
    (synopsis "ELF utils that can check files for security relevant properties")
    (description "A suite of ELF tools to aid auditing systems.
Contains various ELF related utils for ELF32, ELF64 binaries useful
for displaying PaX and security info on a large groups of binary
files.")
    (license license:gpl2+)))

(define-public vtest
  (let ((commit "86e65f1024453b1074d239a88330b5150d3e44bb")
        (revision "1"))
    (package
      (name "vtest")
      (version (git-version "0.0.0" revision commit))
      (source (origin
                (method git-fetch)
                (uri (git-reference
                      (url "https://github.com/vtest/VTest.git")
                      (commit commit)))
                (file-name (git-file-name name version))
                (sha256
                 (base32
                  "13z2j7gnbivzapp3rdf0pjk33rw8kw6rich4aidsi9kr3rc0f3g9"))))
      (build-system gnu-build-system)
      (arguments
       `(#:tests? #f
         #:make-flags (list "CC=gcc")
         #:phases (modify-phases %standard-phases
                    (delete 'configure)
                    (replace 'install
                      (lambda* (#:key outputs #:allow-other-keys)
                        (let* ((out (assoc-ref outputs "out"))
                               (bin-dir (string-append out "/bin")))
                          (mkdir-p bin-dir)
                          (install-file "vtest" bin-dir)
                          #t))))))
      (inputs
       `(("zlib" ,zlib)
         ("pcre" ,pcre)))
      (native-inputs `(("python" ,python-minimal)))
      (home-page "https://github.com/vtest/VTest")
      (synopsis "HTTP test-program")
      (description "VTest is the (almost) unvarnished varnishtest
program, made available as a stand-alone program because it can be
used to test all sorts of HTTP clients, servers and proxies.")
      (license (list license:bsd-2 license:bsd-3)))))

(define-public haproxy
  (package
    (name "haproxy")
    (version "2.0.7")
    (source (origin
              (method url-fetch)
              (uri
               (string-append "https://www.haproxy.org/download/"
                              (version-major+minor version)
                              "/src/haproxy-" version ".tar.gz"))
              (sha256
               (base32
                "1p0kn7f6gq4n9hik8bq9hckfj816m40lw5yx0qjvvlcf09rcswrq"))))
    (build-system gnu-build-system)
    (arguments
     `(#:tests? #f
       #:make-flags
       (list "TARGET=linux-glibc"
             "USE_OPENSSL=yes"
             "USE_PCRE=yes"
             "USE_PCRE_JIT=yes"
             "USE_ZLIB=yes"
             (string-append "PREFIX=" (assoc-ref %outputs "out")))

       #:phases (modify-phases %standard-phases
                  (delete 'configure)
                  ;; TODO: package "VTest" from https://github.com/vtest/VTest
                  ;; (replace 'check
                  ;;   (lambda _
                  ;;     (invoke "scripts/run-regtests.sh")))
                  )))
    (inputs
     `(("zlib" ,zlib)
       ("openssl" ,openssl)
       ("pcre:bin" ,pcre "bin")
       ("gettext" ,gnu-gettext)))
    (native-inputs `(("python" ,python)))
    (home-page "https://www.haproxy.org/")
    (synopsis "High performance tcp/http load balancer")
    (description "High performance tcp/http load balancer.")
    (license (list license:gpl2+ license:lgpl2.1+))))

(define-public modsecurity-standalone
  (package
    (name "modsecurity-standalone")
    (version "2.9.3")
    (source (origin
              (method url-fetch)
              (uri (string-append "https://www.modsecurity.org/tarball/" version
                                  "/modsecurity-" version ".tar.gz"))
              (sha256
               (base32
                "0611nskd2y6yagrciqafxdn4rxbdk2v4swf45kc1sgwx2sfh34j1"))))
    (build-system gnu-build-system)
    (arguments
     `(#:configure-flags
       (list (string-append "--with-curl=" (assoc-ref %build-inputs "curl"))
             (string-append "--with-apxs=" (assoc-ref %build-inputs "httpd") "/bin/apxs")
             (string-append "--with-pcre=" (assoc-ref %build-inputs "pcre:bin") "/bin/pcre-config")
             (string-append "--with-apr=" (assoc-ref %build-inputs "apr"))
             (string-append "--with-apu=" (assoc-ref %build-inputs "apr-util"))
             (string-append "--with-libxml=" (assoc-ref %build-inputs "libxml2"))
             "--disable-apache2-module"
             "--enable-standalone-module"
             "--enable-pcre-study"
             "--without-lua"
             "--enable-pcre-jit")
       #:modules ((srfi srfi-26)
                  ,@%gnu-build-system-modules)
       #:phases (modify-phases %standard-phases
                  (replace 'build
                    (lambda _
                      (invoke "make"
                              "standalone")))
                  (add-after 'install 'install-plugin-headers
                    (lambda* (#:key outputs #:allow-other-keys)
                      (let* ((out (assoc-ref outputs "out"))
                             (include-dir (string-append out "/include"))
                             (install-include (cut install-file <> include-dir)))
                        (mkdir-p include-dir)
                        (for-each install-include
                                  (find-files "standalone" "\\.h$"))
                        (for-each install-include
                                  (find-files "apache2" "\\.h$"))))))))
    (inputs
     `(("apr" ,apr)
       ("apr-util" ,apr-util)
       ("curl" ,curl)
       ("httpd" ,httpd)
       ("pcre" ,pcre)
       ("libxml2" ,libxml2)
       ("libyajl" ,libyajl)
       ("pcre:bin" ,pcre "bin")))
    (native-inputs
     `(("perl" ,perl)
       ("pkg-config" ,pkg-config)))
    (home-page "https://www.modsecurity.org")
    (synopsis "Web application firewall")
    (description "ModSecurity is an open source, cross-platform web
application firewall (WAF) module.  Known as the \"Swiss Army Knife\"
of WAFs, it enables web application defenders to gain visibility into
HTTP(S) traffic and provides a power rules language and API to
implement advanced protections.")
    (license license:asl2.0)))

(define-public apr-union
  (package
    (name "apr-union")
    (version (package-version apr))
    (source #f)
    (build-system trivial-build-system)
    (arguments
     '(#:modules ((guix build union))
       #:builder (begin
                   (use-modules (ice-9 match)
                                (guix build union))
                   (match %build-inputs
                     (((names . directories) ...)
                      (union-build (assoc-ref %outputs "out")
                                   directories)
                      #t)))))
    (inputs `(("apr" ,apr)
              ("apr-util" ,apr-util)))
    (synopsis "Union of APR libraries")
    (description
     "A union of APR and its extension utilities.  A union is required
because haproxy SPOA builds assume that all of the headers and
libraries are in the same directory.")
    (home-page (package-home-page apr))
    (license (package-license apr))))


(define-public haproxy-modsecurity
  (package
    (inherit haproxy)
    (name "haproxy-modsecurity")
    (arguments
     `(#:tests? #f
       #:phases (modify-phases %standard-phases
                  (delete 'configure)
                  (replace 'build
                    (lambda* (#:key inputs #:allow-other-keys)
                      (let* ((modsecurity (assoc-ref inputs "modsecurity"))
                             (modsec-includes (string-append modsecurity "/include"))
                             (modsec-lib (string-append modsecurity "/lib"))
                             (httpd (assoc-ref inputs "httpd"))
                             (httpd-includes (string-append httpd "/include"))
                             (apr (assoc-ref inputs "apr-union"))
                             (apr-includes (string-append apr "/include/apr-1"))
                             (libxml (assoc-ref inputs "libxml2"))
                             (libxml-includes (string-append libxml "/include/libxml2"))
                             (libevent (assoc-ref inputs "libevent"))
                             (libevent-includes (string-append libevent "/include")))
                        (invoke "make" "-C" "contrib/modsecurity" "CC=gcc"
                                (string-append "MODSEC_INC=" modsec-includes)
                                (string-append "MODSEC_LIB=" modsec-lib)
                                (string-append "APACHE2_INC=" httpd-includes)
                                (string-append "APR_INC=" apr-includes)
                                (string-append "LIBXML_INC=" libxml-includes)
                                (string-append "EVENT_INC=" libevent-includes))
                        #t)))
                  (replace 'install
                    (lambda* (#:key outputs #:allow-other-keys)
                      (let* ((out (assoc-ref outputs "out"))
                             (bin-dir (string-append out "/bin")))
                        (mkdir-p bin-dir)
                        (install-file "contrib/modsecurity/modsecurity" bin-dir)
                        #t))))))
    (inputs
     `(("modsecurity" ,modsecurity-standalone)
       ("apr-union" ,apr-union)
       ("httpd" ,httpd)
       ("libevent" ,libevent)
       ("libyajl" ,libyajl)
       ("curl" ,curl)
       ("pcre" ,pcre )
       ("libxml2" ,libxml2)))))
